package com.ihr360.rest.core;

import org.springframework.util.Assert;

import java.util.HashMap;
import java.util.Map;
import java.util.regex.Pattern;

/**
 * Configuration for metadata exposure.
 *
 * @author David wei
 */
public class Ihr360MetadataConfiguration {
    private final Map<Class<?>, Ihr360JsonSchemaFormat> schemaFormats = new HashMap<Class<?>, Ihr360JsonSchemaFormat>();
    private final Map<Class<?>, Pattern> patterns = new HashMap<Class<?>, Pattern>();
    private boolean omitUnresolvableDescriptionKeys = true;
    private boolean alpsEnabled = true;

    /**
     * Configures whether to omit documentation attributes for unresolvable resource bundle keys. Defaults to
     * {@literal true}, which means that an unsuccessful attempt to resolve the message will cause no documentation entry
     * to be rendered for the metadata resources.
     *
     * @param omitUnresolvableDescriptionKeys whether to omit documentation attributes for unresolvable resource bundle
     *          keys.
     */
    public void setOmitUnresolvableDescriptionKeys(boolean omitUnresolvableDescriptionKeys) {
        this.omitUnresolvableDescriptionKeys = omitUnresolvableDescriptionKeys;
    }

    /**
     * Returns whether to omit documentation attributes for unresolvable resource bundle keys.
     *
     * @return the omitUnresolvableDescriptionKeys
     */
    public boolean omitUnresolvableDescriptionKeys() {
        return omitUnresolvableDescriptionKeys;
    }

    /**
     * Configures whether to expose the ALPS resources.
     *
     * @param alpsEnabled the alpsEnabled to set
     */
    public void setAlpsEnabled(boolean enableAlps) {
        this.alpsEnabled = enableAlps;
    }

    /**
     * Returns whether the ALPS resources are exposed.
     *
     * @return the alpsEnabled
     */
    public boolean alpsEnabled() {
        return alpsEnabled;
    }

    public void registerIhr360JsonSchemaFormat(Ihr360JsonSchemaFormat format, Class<?>... types) {

        Assert.notNull(format, "Ihr360JsonSchemaFormat must not be null!");

        for (Class<?> type : types) {
            schemaFormats.put(type, format);
        }
    }

    /**
     * Returns the {@link Ihr360JsonSchemaFormat} to be used for the given type.
     *
     * @param type must not be {@literal null}.
     * @return
     */
    public Ihr360JsonSchemaFormat getSchemaFormatFor(Class<?> type) {
        return schemaFormats.get(type);
    }

    /**
     * Registers the given formatting patter for the given value type.
     *
     * @param pattern must not be {@literal null} or empty.
     * @param type must not be {@literal null}.
     */
    public void registerFormattingPatternFor(String pattern, Class<?> type) {

        Assert.hasText(pattern, "Pattern must not be null or empty!");
        Assert.notNull(type, "Type must not be null!");

        this.patterns.put(type, Pattern.compile(pattern));
    }

    /**
     * Returns the {@link Pattern} registered for the given value type.
     *
     * @param type must not be {@literal null}.
     * @return
     */
    public Pattern getPatternFor(Class<?> type) {

        Assert.notNull(type, "Type must not be null!");

        for (Map.Entry<Class<?>, Pattern> entry : this.patterns.entrySet()) {
            if (entry.getKey().isAssignableFrom(type)) {
                return entry.getValue();
            }
        }

        return this.patterns.get(type);
    }
}